package model.strategies;

import java.awt.geom.Point2D;

import model.GameConstants;
import model.GameEntity;

public class MoveablePlayerStrategy extends AbstractStrategy {
	
	public MoveablePlayerStrategy(GameEntity entity) {
		super(entity);
	}

	@Override
	public void update(int elapsedTimeInMillis) {
		updateOrientation(elapsedTimeInMillis);
		updateSpeed(elapsedTimeInMillis);
		updatePosition(elapsedTimeInMillis);
	}

	/**
	 * Allows players to update their orientation at a defined time
	 * @param elapsedTimeInMillis the time at which to execute the command
	 */
	protected void updateOrientation(int elapsedTimeInMillis) {
		double angularVelocity = entity.getAngularVelocity();
		angularVelocity = Math.max(angularVelocity,
				GameConstants.MINIMUM_PLAYER_ANGULAR_VELOCITY);
		angularVelocity = Math.min(angularVelocity,
				GameConstants.MAXIMUM_PLAYER_ANGULAR_VELOCITY);
		double orientation = this.entity.getOrientation();
		orientation += angularVelocity * (elapsedTimeInMillis / 1000.0);
		this.entity.setOrientation(orientation);
	}

	/**
	 * Updates the speed of the movable player
	 * @param elapsedTimeInMillis The time at which to execute the command in milliseconds
	 */
	protected void updateSpeed(int elapsedTimeInMillis) {
		if (entity.getAcceleration() != 0.0) {
			double speed = entity.getSpeed();
			double acceleration = entity.getAcceleration();
			acceleration = Math.max(acceleration,
					GameConstants.MINIMUM_PLAYER_ACCELERATION);
			acceleration = Math.min(acceleration,
					GameConstants.MAXIMUM_PLAYER_ACCELERATION);
			speed += acceleration * (elapsedTimeInMillis / 1000.0);
			speed = Math.max(speed, GameConstants.MINIMUM_PLAYER_SPEED);
			speed = Math.min(speed, GameConstants.MAXIMUM_PLAYER_SPEED);
			this.entity.setSpeed(speed);
		}
	}
	/**
	 * Updates the position of the movable player
	 * @param elapsedTimeInMillis The time at which to execute the command in milliseconds
	 */
	protected void updatePosition(int elapsedTimeInMillis) {
		if (entity.getSpeed() != 0.0) {
			double speed = entity.getSpeed();
			double orientation = entity.getOrientation();
			Point2D position = entity.getPosition();
			double newPosX = position.getX() + speed
					* (elapsedTimeInMillis / 1000.0)
					* Math.sin(Math.toRadians(orientation));
			double newPosY = position.getY() + speed
					* (elapsedTimeInMillis / 1000.0)
					* Math.cos(Math.toRadians(orientation));
			position.setLocation(newPosX, newPosY);
		}
	}
}
